package com.shide.common.util;

import java.lang.reflect.Field;
import java.util.*;

import com.shide.common.annotation.FieldName;
import com.shide.common.base.BaseDict;
import com.shide.common.base.NoTranslation;
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
 * 对象对比
 *
 * @author yuwg
 */
@NoArgsConstructor
public class ChangeTracker {


    /**
     * 新旧对象对比，如果发生变化，则进行记录
     *
     * @param oldObj 旧对象
     * @param newObj 新对象
     * @return 变更记录
     */
    public static Map<String, List<ChangeRecord>> trackChangesForCategory(Object oldObj, Object newObj) {
        Map<String, List<ChangeRecord>> categorizedChanges = new HashMap<>();

        if (oldObj.getClass() != newObj.getClass()) {
            throw new IllegalArgumentException("Objects must be of the same class");
        }

        Field[] fields = oldObj.getClass().getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            try {

                // 只处理标注了 @FieldName 的字段
                if (field.isAnnotationPresent(FieldName.class)) {
                    FieldName fieldNameAnnotation = field.getAnnotation(FieldName.class);
                    String fieldName = fieldNameAnnotation.value();
                    String category = fieldNameAnnotation.category();
                    Class<? extends BaseDict> dictionaryEnumClass = fieldNameAnnotation.dict();

                    Object oldValue = field.get(oldObj);
                    Object newValue = field.get(newObj);

                    // 仅当 dictionaryEnum 不为默认值时执行翻译
                    if (dictionaryEnumClass != NoTranslation.class) {
                        BaseDict dict = getEnumInstance(dictionaryEnumClass);
                        oldValue = dict.translate(Integer.valueOf(oldValue.toString()));
                        newValue = dict.translate(Integer.valueOf(newValue.toString()));
                    }
                    if ((oldValue == null && newValue != null) || (oldValue != null && !oldValue.equals(newValue))) {
                        ChangeRecord changeRecord = new ChangeRecord(fieldName, oldValue, newValue);
                        // 将变更记录按分类存储

                        categorizedChanges.computeIfAbsent(category, k -> new ArrayList<>()).add(changeRecord);

                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("日志对比异常");
            }

        }

        return categorizedChanges;
    }

    /**
     * 新旧对象对比，如果发生变化，则进行记录
     *
     * @param oldObj 旧对象
     * @param newObj 新对象
     * @return 变更记录
     */
    public static List<ChangeRecord> trackChangesForList(Object oldObj, Object newObj) {
        List<ChangeRecord> changeRecordList = new ArrayList<>();

        if (oldObj.getClass() != newObj.getClass()) {
            throw new IllegalArgumentException("Objects must be of the same class");
        }

        Field[] fields = oldObj.getClass().getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            try {

                // 只处理标注了 @FieldName 的字段
                if (field.isAnnotationPresent(FieldName.class)) {
                    FieldName fieldNameAnnotation = field.getAnnotation(FieldName.class);
                    String fieldName = fieldNameAnnotation.value();
                    Class<? extends BaseDict> dictionaryEnumClass = fieldNameAnnotation.dict();

                    Object oldValue = field.get(oldObj);
                    Object newValue = field.get(newObj);

                    // 仅当 dictionaryEnum 不为默认值时执行翻译
                    if (dictionaryEnumClass != NoTranslation.class) {
                        BaseDict dict = getEnumInstance(dictionaryEnumClass);
                        oldValue = dict.translate(Integer.valueOf(oldValue.toString()));
                        newValue = dict.translate(Integer.valueOf(newValue.toString()));
                    }
                    if ((oldValue == null && newValue != null) || (oldValue != null && !oldValue.equals(newValue))) {
                        ChangeRecord changeRecord = new ChangeRecord(fieldName, oldValue, newValue);
                        // 将变更记录按分类存储
                        changeRecordList.add(changeRecord);

                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("日志对比异常");
            }

        }

        return changeRecordList;
    }


    private static BaseDict getEnumInstance(Class<? extends BaseDict> dict) {
        return dict.getEnumConstants()[0];
    }


    @Getter
    public static class ChangeRecord {
        private final String fieldName;

        private final Object oldValue;

        private final Object newValue;

        public ChangeRecord(String field, Object oldValue, Object newValue) {
            this.fieldName = field;
            this.oldValue = oldValue;
            this.newValue = newValue;
        }

        @Override
        public String toString() {
            return fieldName + "由【" + oldValue + "】改为【" + newValue + "】";
        }
    }

}
